home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1429 / iconwnd.cpp < prev    next >
C/C++ Source or Header  |  1995-08-27  |  13KB  |  498 lines

  1. //    ************************************************************
  2. //
  3. //    System-Click Notification Icon
  4. //    Win95 32-bit Shell Extension
  5. //        James P. Ketrenos
  6. //
  7. //    ************************************************************
  8. #include <afx.h>
  9. #include <shlobj.h>    //    SHAddToRecentDocs()
  10. //    NOTE:    I had to comment out line 139 in OAIDL.H in order to get it to compile with shlobj.h.
  11. //            The line commented out redefined BSTR
  12.  
  13. #include "Resource.h"
  14. #include "Global.h"
  15. #include "IconWnd.h"
  16.  
  17.  
  18.  
  19. //    ************************************************************
  20. //    CIconWnd Class Implementation
  21. //
  22. //    Purpose:
  23. //    *    Respond to Notification Button actions.
  24. //    *    Respond to WM_WININICHANGE messages to keep tool-tip 
  25. //        up to date.
  26. //    *    Keep the system INI and registry up to date with all
  27. //        the latest values as we change them.
  28. //    ************************************************************
  29.  
  30. BEGIN_MESSAGE_MAP(CIconWnd, CFrameWnd)
  31.     ON_COMMAND(IDC_FULLDRAG, OnFullDrag)
  32.     ON_COMMAND(IDC_ANIMATED, OnAnimated)
  33.     ON_COMMAND(IDC_CLRDOCS, OnClearDocs)
  34.     ON_COMMAND(IDC_ABOUT, OnAbout)
  35.     ON_COMMAND(IDC_APPHELP, OnHelp)
  36.     ON_COMMAND(IDCLOSE, OnClose)
  37.     ON_MESSAGE(SC_WM_NOTIFYICON, OnNotifyIcon)
  38.     ON_WM_DESTROY()
  39.     ON_WM_TIMER()
  40.     ON_WM_WININICHANGE()
  41. END_MESSAGE_MAP()
  42.  
  43.  
  44.  
  45. //    ************************************************************
  46. //    Message-Mapped Functions
  47. //    ************************************************************
  48.  
  49.  
  50.  
  51. //    *******************************
  52. //    CIconWnd::OnWinIniChange()
  53. //
  54. //    Purpose:
  55. //    *    Respond to the system WM_WININICHANGE message
  56. //    *    If the [Windows] section has been altered, re-fetch
  57. //        our settings from the system and update our variables.
  58. //    *    Update the Notification Icon accordingly
  59. //    *******************************
  60. void    CIconWnd::OnWinIniChange(LPCTSTR lpszSection)
  61. {
  62. CString    String    = "WINDOWS";
  63.     
  64.     if (!String.CompareNoCase(lpszSection))
  65.     {
  66.         m_Fetch();
  67.  
  68.         m_UpdateIconTip();
  69.         
  70.         //    Check to see if Windows Extension #1 is installed
  71.         m_bExtension1    = SystemParametersInfo(SPI_GETWINDOWSEXTENSION, 1, 0, 0);
  72.     }
  73.     
  74. }
  75.  
  76.  
  77.  
  78. //    *******************************
  79. //    CIconWnd::OnAbout()
  80. //
  81. //    Purpose:
  82. //    *    Check to see if our About window is already up.
  83. //    +    If so, make the current one the foreground active window
  84. //    +    If not, create the About window and display it.
  85. //    *******************************
  86. void    CIconWnd::OnAbout()
  87. {
  88. CWnd*    pWnd    = FindWindow(NULL, "About System-Click . . .");
  89.  
  90.     if (!pWnd)
  91.     {
  92.     CDialog    About(IDD_ABOUT, this);
  93.  
  94.         About.DoModal();
  95.     }
  96.     else
  97.         pWnd->SetForegroundWindow();
  98. }
  99.  
  100.  
  101.  
  102. //    *******************************
  103. //    CIconWnd::OnHelp()
  104. //
  105. //    Purpose:
  106. //    *    Check to see if our Help window is already up.
  107. //    +    If so, make the current one the foreground active window
  108. //    +    If not, create the Help window and display it.
  109. //    *******************************
  110. void    CIconWnd::OnHelp()
  111. {
  112. CWnd*    pWnd    = FindWindow(NULL, "System-Click Help");
  113.  
  114.     if (!pWnd)
  115.     {
  116.     CDialog    Help(IDD_HELP, this);
  117.  
  118.         Help.DoModal();
  119.     }
  120.     else
  121.         pWnd->SetForegroundWindow();
  122. }
  123.  
  124.  
  125. //    *******************************
  126. //    CIconWnd::OnClearDocs()
  127. //
  128. //    Purpose:
  129. //    *    Clears the Recent Document list in the Start Menus
  130. //    *******************************
  131. void    CIconWnd::OnClearDocs()
  132. {
  133.     //    Clears the document list
  134.     ::SHAddToRecentDocs(NULL, NULL);//SHARD_PATH, NULL); //SHARD_PIDL, NULL);
  135. }
  136.  
  137.  
  138. //    *******************************
  139. //    CIconWnd::OnAnimated()
  140. //
  141. //    Purpose:
  142. //    *    Toggle the Animated Window flag
  143. //    *    Update the Notification Icon Tool-Tip to reflect current state
  144. //    *    Update the Win95 system parameters
  145. //    *******************************
  146. void    CIconWnd::OnAnimated()
  147. {
  148. ANIMATIONINFO    Animated;
  149.  
  150.     m_bAnimated    = (m_bAnimated ? FALSE : TRUE);
  151.  
  152.     m_UpdateIconTip();
  153.     
  154.     //    Update the system parameter, save the setting in the Windows INI file, and let
  155.     //    all top level windows know we have changed a system parameter.
  156.     Animated.cbSize            = sizeof(ANIMATIONINFO);
  157.     Animated.iMinAnimate    = m_bAnimated;
  158.  
  159.     SystemParametersInfo(
  160.         SPI_SETANIMATION, 
  161.         0, 
  162.         &Animated, 
  163.         SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  164. }
  165.  
  166.  
  167.  
  168. //    *******************************
  169. //    CIconWnd::OnFullDrag()
  170. //
  171. //    Purpose:
  172. //    *    Toggle the Full Dragging flag
  173. //    *    Update the Notification Icon Tool-Tip to reflect current state
  174. //    *    Update the Win95 system parameters
  175. //    *******************************
  176. void    CIconWnd::OnFullDrag()
  177. {
  178.     m_bFullDrag    = (m_bFullDrag ? FALSE : TRUE);
  179.  
  180.     m_UpdateIconTip();
  181.     
  182.     //    Update the system parameter, save the setting in the Windows INI file, and let
  183.     //    all top level windows know we have changed a system parameter.
  184.     SystemParametersInfo(
  185.         SPI_SETDRAGFULLWINDOWS, 
  186.         m_bFullDrag, 
  187.         0, 
  188.         SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  189. }
  190.  
  191.  
  192.  
  193. //    ************************************************************
  194. //    General Class Functions
  195. //    ************************************************************
  196.  
  197.  
  198.  
  199. //    *******************************
  200. //    CIconWnd::CIconWnd()
  201. //
  202. //    Purpose:
  203. //    *    Place keeper
  204. //    *******************************
  205. CIconWnd::CIconWnd()
  206. {
  207. }
  208.  
  209.  
  210.  
  211. //    *******************************
  212. //    CIconWnd::~CIconWnd()
  213. //
  214. //    Purpose:
  215. //    *    Place keeper
  216. //    *******************************
  217. CIconWnd::~CIconWnd()
  218. {
  219. }
  220.  
  221.  
  222.  
  223. //    *******************************
  224. //    CIconWnd::m_UpdateIconTip()
  225. //
  226. //    Purpose:
  227. //    *    Updates the Notification Icon Tool-Tip to refelct
  228. //        current variable states.
  229. //    *******************************
  230. void    CIconWnd::m_UpdateIconTip()
  231. {
  232. NOTIFYICONDATA    nidSysClk;
  233.  
  234.     nidSysClk.cbSize    = sizeof(NOTIFYICONDATA);
  235.     nidSysClk.hWnd        = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
  236.     nidSysClk.uID        = IDI_SYSCLK;
  237.     nidSysClk.uFlags    = NIF_TIP;
  238.     wsprintf(
  239.         nidSysClk.szTip, 
  240.         "FD: %s  AW: %s", 
  241.         m_bFullDrag ? "ON" : "OFF",
  242.         m_bAnimated ? "ON" : "OFF");
  243.  
  244.     Shell_NotifyIcon(NIM_MODIFY, &nidSysClk);
  245. }
  246.         
  247.  
  248.  
  249. //    *******************************
  250. //    CIconWnd::m_Fetch()
  251. //
  252. //    Purpose:
  253. //    *    Fetch system settings from Win95
  254. //    *******************************
  255. void    CIconWnd::m_Fetch()
  256. {
  257. ANIMATIONINFO    Animated;
  258.  
  259.     SystemParametersInfo(
  260.         SPI_GETDRAGFULLWINDOWS, 
  261.         0, 
  262.         &m_bFullDrag,
  263.         0);
  264.  
  265.     Animated.cbSize            = sizeof(ANIMATIONINFO);
  266.     SystemParametersInfo(
  267.         SPI_GETANIMATION, 
  268.         0, 
  269.         &Animated, 
  270.         0);
  271.     m_bAnimated    = Animated.iMinAnimate ? TRUE : FALSE;
  272. }
  273.  
  274.  
  275.  
  276. //    *******************************
  277. //    CIconWnd::OnTimer()
  278. //
  279. //    Purpose:
  280. //    *    Called .5 seconds after the Notification Icon is activated
  281. //    *    Provide functionality for Notification Icon
  282. //    *    Keeps stray mouse button clicks from dismissing menu before
  283. //        it has displayed.
  284. //    *******************************
  285. void    CIconWnd::OnTimer(UINT nIDEvent)
  286. {
  287.     if (nIDEvent == IDT_CLOSE)
  288.     {
  289.         SendMessage(WM_CLOSE);
  290.     }
  291.  
  292.     if (nIDEvent == IDT_POPUP)
  293.     {
  294.     CMenu    hPopup;
  295.     POINT    Point;
  296.     HWND    hOrigActive;
  297.  
  298.         //    Kill the timer
  299.         KillTimer(m_Timer);
  300.         m_Timer    = 0;
  301.  
  302.         //    Create our menu
  303.         hPopup.CreatePopupMenu();
  304.         
  305.         if (m_bExtension1)    //    Requires Extension1 Pack to be installed
  306.             hPopup.AppendMenu(MF_STRING, IDC_FULLDRAG, "&Full Drag");    
  307.  
  308.         //    Standard Win95 functionality
  309.         hPopup.AppendMenu(MF_STRING, IDC_ANIMATED, "&Animated Windows");
  310.         hPopup.AppendMenu(MF_STRING, IDC_CLRDOCS, "&Clear Recent Doc List");
  311.  
  312.         //    Generic program menu items
  313.         hPopup.AppendMenu(MF_SEPARATOR);
  314.         hPopup.AppendMenu(MF_STRING, IDC_ABOUT, "A&bout . . .");
  315.         hPopup.AppendMenu(MF_STRING, IDC_APPHELP, "&Help");
  316.         //hPopup.AppendMenu(MF_STRING, IDCLOSE, "E&xit");
  317.         
  318.         //    Set the initial checks correctly
  319.         hPopup.CheckMenuItem(IDC_ANIMATED, MF_BYCOMMAND | (m_bAnimated ? MF_CHECKED : MF_UNCHECKED));
  320.         
  321.         if (m_bExtension1)
  322.             hPopup.CheckMenuItem(IDC_FULLDRAG, MF_BYCOMMAND | (m_bFullDrag ? MF_CHECKED : MF_UNCHECKED));
  323.  
  324.         //    Get the currently active window, set our window to active, pop up the menu, and
  325.         //    then return the system state to the way it was.
  326.             
  327.         hOrigActive    = ::GetForegroundWindow();
  328.         SetForegroundWindow();
  329.         ::GetCursorPos(&Point);
  330.         hPopup.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, Point.x, Point.y, this, NULL);
  331.         ::SetForegroundWindow(hOrigActive);
  332.  
  333.         //    Destroy our menu to insure our resources are freed
  334.         hPopup.DestroyMenu();
  335.  
  336.         return;
  337.     }
  338. }
  339.  
  340.  
  341.  
  342. //    *******************************
  343. //    CIconWnd::OnNotifyIcon()
  344. //    
  345. //    Purpose:
  346. //    *    Notification Icon callback function
  347. //    *    If the user left clicks on the icon, pop up the toggle button window.
  348. //    *    If the user double-clicks on the icon, toggle the current mode.
  349. //
  350. //    NOTE:    Because of the magic in Win95, it is better not to do any actual
  351. //            processing immediately after we encounter our message from the
  352. //            Notification Icon.  
  353. //            
  354. //            It is better to trigger a Timer and respond to the WM_TIMER message.  
  355. //            This gives the system enough time to flush out the stray mouse 
  356. //            messages before our code actually takes place.
  357. //
  358. //            It appears as if the OS gives our program the mouse messages first, and 
  359. //            then hands them to the Taskbar after we take them.  If we do not wait
  360. //            and immediately do a TrackPopupMenu(), the stray mouse clicks may
  361. //            dismiss this menu.  Likewise, if we close the application immediately,
  362. //            the mouse clicks that triggered our app to shutdown will be fed to
  363. //            the task bar and may cause adverse effects.
  364. //    *******************************
  365. LONG    CIconWnd::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
  366. {
  367. UINT    uID;
  368. UINT    uMsg;
  369. BOOL    bFDOriginal    = m_bFullDrag;
  370. BOOL    bAWOriginal    = m_bAnimated;
  371.  
  372.     uID        = (UINT)wParam;
  373.     uMsg    = (UINT)lParam;
  374.  
  375.     if ((uMsg == WM_RBUTTONDBLCLK) && (uID == IDI_SYSCLK))
  376.     {
  377.         m_Timer    = SetTimer(IDT_CLOSE, 500, NULL);
  378.         
  379.         return    0L;
  380.     }
  381.     
  382.     if ((uMsg == WM_LBUTTONDOWN) && (uID == IDI_SYSCLK))
  383.     {
  384.         m_Timer    = SetTimer(IDT_POPUP, 500, NULL);
  385.  
  386.         return    0L;
  387.     }
  388.         
  389.     return 0L;
  390. }
  391.  
  392.  
  393.  
  394. //    *******************************
  395. //    CIconWnd::m_InitIcon()
  396. //
  397. //    Purpose:
  398. //    *    Fetch the Full-Drag option from our INI file
  399. //    *    Initialize the Notification Icon
  400. //    *    Set the SystemParameterInfo() setting for the Full Dragging
  401. //        accordingly.
  402. //    Returns:
  403. //    TRUE    Success
  404. //    FALSE    Failure, either from Shell_NotifyIcon
  405. //    *******************************
  406. BOOL    CIconWnd::m_InitIcon()
  407. {
  408. NOTIFYICONDATA    nidSysClk;
  409. BOOL            bRetVal;
  410. HICON            hIcon;
  411. ANIMATIONINFO    Animated;
  412.  
  413.     //    Fetch entries from our INI file [defaults = FALSE]
  414.     //    NOTE:    We don't do this since all our settings are saved in the
  415.     //            windows INI and in the registry.
  416.     //m_bFullDrag    = AfxGetApp()->GetProfileInt("General", "Full Drag", 0);
  417.     //m_bAnimated    = AfxGetApp()->GetProfileInt("General", "Animated", 0);
  418.  
  419.     //    Fetch current values from the System settings
  420.     m_Fetch();
  421.     
  422.     //    Latch the Notification Icon into the Notification Area
  423.     hIcon        = AfxGetApp()->LoadIcon(MAKEINTRESOURCE(IDI_SYSCLK));
  424.     
  425.     nidSysClk.cbSize            = sizeof(NOTIFYICONDATA);
  426.     nidSysClk.hWnd                = GetSafeHwnd();
  427.     nidSysClk.uID                = IDI_SYSCLK;
  428.     nidSysClk.uFlags            = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  429.     nidSysClk.uCallbackMessage    = SC_WM_NOTIFYICON;
  430.     nidSysClk.hIcon                = hIcon; 
  431.     wsprintf(
  432.         nidSysClk.szTip, 
  433.         "FD: %s  AW: %s", 
  434.         m_bFullDrag ? "ON" : "OFF",
  435.         m_bAnimated ? "ON" : "OFF");
  436.     
  437.     bRetVal    = Shell_NotifyIcon(NIM_ADD, &nidSysClk);
  438.  
  439.     if (hIcon)
  440.         DestroyIcon(hIcon);
  441.  
  442.     //    Update the system parameter, save the setting in the Windows INI file, and let
  443.     //    all top level windows know we have changed a system parameter.
  444.     SystemParametersInfo(
  445.         SPI_SETDRAGFULLWINDOWS, 
  446.         m_bFullDrag, 
  447.         0, 
  448.         SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  449.  
  450.     Animated.cbSize            = sizeof(ANIMATIONINFO);
  451.     Animated.iMinAnimate    = m_bAnimated;
  452.  
  453.     SystemParametersInfo(
  454.         SPI_SETANIMATION, 
  455.         0, 
  456.         &Animated, 
  457.         SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  458.                
  459.     return    bRetVal;
  460. }
  461.  
  462.  
  463.  
  464. //    *******************************
  465. //    CIconWnd::OnDestroy()
  466. //
  467. //    Purpose:
  468. //    *    Delete the notification icon from the Notification area.
  469. //    *    Save the System-Click setting to our INI setting.
  470. //
  471. //    *******************************
  472. void    CIconWnd::OnDestroy()
  473. {
  474. NOTIFYICONDATA    nidSysClk;
  475.  
  476.     //    Verify that we do not have a timer allocated
  477.     if (m_Timer)
  478.     {
  479.         KillTimer(m_Timer);
  480.         m_Timer    = 0;
  481.     }
  482.     
  483.     //    Remove the Notification Icon from the Notification area
  484.     nidSysClk.cbSize    = sizeof(NOTIFYICONDATA);
  485.     nidSysClk.hWnd        = GetSafeHwnd();
  486.     nidSysClk.uID        = IDI_SYSCLK;
  487.     
  488.     Shell_NotifyIcon(NIM_DELETE, &nidSysClk);
  489.  
  490.     //    Save our setting to the INI file
  491.     //    NOTE:    We don't do this since all our settings are saved in the
  492.     //            windows INI and in the registry.
  493.     //AfxGetApp()->WriteProfileInt("General", "SysClk", m_bFullDrag);
  494.     //AfxGetApp()->WriteProfileInt("General", "Animated", m_bAnimated);
  495.     
  496.     CWnd::OnDestroy();
  497. }
  498.